<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Tags Filter Example</title>
        <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
        <style>
            body {
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                height: 100vh;
                margin: 0;
                padding: 20px;
                overflow: hidden;
                display: flex;
                align-items: center;
                justify-content: center;
            }
            .container {
                max-width: 900px;
                height: calc(100vh - 40px);
                display: flex;
                flex-direction: column;
            }
            .card {
                border: 2px solid rgba(255,255,255,0.2);
                border-radius: 0;
                box-shadow: 0 4px 6px rgba(0,0,0,0.1);
                height: 100%;
                display: flex;
                flex-direction: column;
            }
            .card-body {
                flex: 1;
                overflow: hidden;
                display: flex;
                flex-direction: column;
            }
            .card-header {
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                color: white;
                border-radius: 0;
                padding: 20px;
                border-bottom: 2px solid rgba(255,255,255,0.3);
            }
            .card-header h1 {
                margin: 0;
                font-size: 24px;
                font-weight: 600;
            }
            .card-header a {
                color: white;
                text-decoration: none;
                opacity: 0.9;
                transition: opacity 0.2s;
            }
            .card-header a:hover {
                opacity: 1;
                text-decoration: underline;
            }
            .protocol-badge {
                display: inline-block;
                padding: 4px 12px;
                border-radius: 0;
                font-size: 12px;
                font-weight: 600;
                margin-left: 10px;
                border: 1px solid rgba(255,255,255,0.5);
            }
            .protocol-protobuf {
                background: #10b981;
                color: white;
            }
            .protocol-json {
                background: #3b82f6;
                color: white;
            }
            #status {
                padding: 12px;
                border-radius: 0;
                font-weight: 500;
                margin-bottom: 20px;
                border: 1px solid;
            }
            .status-connected {
                background: #d1fae5;
                color: #065f46;
                border-color: #10b981;
            }
            .status-disconnected {
                background: #fee2e2;
                color: #991b1b;
                border-color: #ef4444;
            }
            .status-connecting {
                background: #fef3c7;
                color: #92400e;
                border-color: #f59e0b;
            }
            .controls {
                background: #f8fafc;
                padding: 20px;
                border-radius: 0;
                margin-bottom: 20px;
                border: 1px solid #e2e8f0;
            }
            .controls label {
                font-weight: 600;
                color: #334155;
                margin-right: 10px;
            }
            #tickerSelect {
                padding: 8px 16px;
                border: 2px solid #e2e8f0;
                border-radius: 0;
                font-size: 14px;
                font-weight: 500;
                color: #1e293b;
                transition: all 0.3s;
            }
            #tickerSelect:focus {
                outline: none;
                border-color: #667eea;
                box-shadow: none;
            }
            .messages-container {
                flex: 1;
                overflow: hidden;
                display: flex;
                flex-direction: column;
            }
            #messages {
                list-style: none;
                padding: 0;
                margin: 0;
                overflow-y: auto;
                flex: 1;
            }
            #messages li {
                padding: 12px 16px;
                margin-bottom: 8px;
                background: white;
                border-radius: 0;
                border-left: 3px solid #667eea;
                border-top: 1px solid #e2e8f0;
                border-right: 1px solid #e2e8f0;
                border-bottom: 1px solid #e2e8f0;
                font-size: 14px;
                line-height: 1.6;
                animation: slideIn 0.3s ease;
            }
            @keyframes slideIn {
                from {
                    opacity: 0;
                    transform: translateY(-10px);
                }
                to {
                    opacity: 1;
                    transform: translateY(0);
                }
            }
            #messages li:nth-child(even) {
                border-left-color: #764ba2;
            }
            .message-time {
                color: #64748b;
                font-size: 12px;
                font-weight: 600;
            }
            .message-content {
                color: #1e293b;
                margin-left: 10px;
            }
            .info-text {
                background: #eff6ff;
                border: 1px solid #bfdbfe;
                border-radius: 0;
                padding: 12px;
                margin-top: 5px;
                margin-bottom: 10px;
                font-size: 13px;
                color: #1e40af;
            }
            .info-text code {
                background: #dbeafe;
                padding: 2px 6px;
                border-radius: 0;
                font-family: 'Courier New', monospace;
                color: #1e3a8a;
            }
            ::-webkit-scrollbar {
                width: 8px;
            }
            ::-webkit-scrollbar-track {
                background: #f1f5f9;
                border-radius: 0;
            }
            ::-webkit-scrollbar-thumb {
                background: #cbd5e1;
                border-radius: 0;
            }
            ::-webkit-scrollbar-thumb:hover {
                background: #94a3b8;
            }
        </style>
        {{if .UseProtobuf}}
        <script src="https://unpkg.com/text-encoding@0.6.4/lib/encoding-indexes.js"></script>
        <script src="https://unpkg.com/text-encoding@0.6.4/lib/encoding.js"></script>
        <script type="text/javascript" src="https://unpkg.com/centrifuge@^5.5/dist/centrifuge.protobuf.js"></script>
        {{else}}
        <script type="text/javascript" src="https://unpkg.com/centrifuge@^5.5/dist/centrifuge.js"></script>
        {{end}}
        <script type="text/javascript">
            const useProtobuf = {{.UseProtobuf}};
            // helper functions to work with escaping html.
            const tagsToReplace = {'&': '&amp;', '<': '&lt;', '>': '&gt;'};
            function replaceTag(tag) {return tagsToReplace[tag] || tag;}

            const channel = "tickers";
            let currentSubscription = null;

            window.addEventListener('load', function() {
                const container = document.getElementById('messages');
                const tickerSelect = document.getElementById('tickerSelect');
                const statusDiv = document.getElementById('status');

                const centrifuge = new Centrifuge('ws://localhost:8000/connection/websocket', {});

                centrifuge.on('connecting', function(ctx){
                    drawText('Connecting: ' + ctx.reason);
                    statusDiv.className = 'status-connecting';
                    statusDiv.textContent = '⏳ Connecting...';
                });

                centrifuge.on('disconnected', function(ctx){
                    drawText('Disconnected: ' + ctx.reason);
                    statusDiv.className = 'status-disconnected';
                    statusDiv.textContent = '❌ Disconnected';
                });

                // bind listeners on centrifuge object instance events.
                centrifuge.on('connected', function(ctx){
                    const mode = useProtobuf ? 'protobuf' : 'JSON';
                    drawText('Connected with client ID ' + ctx.client + ' over ' + ctx.transport + ' (using ' + mode + ' protocol)');
                    statusDiv.className = 'status-connected';
                    statusDiv.textContent = '✓ Connected - ready to subscribe';

                    // Initial subscription with default ticker.
                    subscribeToTicker(tickerSelect.value);
                });

                // Function to create new subscription with tags filter
                function subscribeToTicker(ticker) {
                    statusDiv.textContent = 'Subscribing to ticker: ' + ticker;

                    const tagsFilter = {
                        key: "ticker",
                        cmp: "eq",
                        val: ticker
                    };

                    if (!currentSubscription) {
                        currentSubscription = centrifuge.newSubscription(channel, {
                            tagsFilter: tagsFilter
                        });
                        currentSubscription.on("publication", handlePublication)
                            .on("unsubscribed", handleUnsubscribed)
                            .on("subscribed", handleSubscribed)
                            .on("subscribing", handleSubscribing)
                            .on("error", handleSubscriptionError);
                    } else {
                        currentSubscription.unsubscribe();
                        currentSubscription.setTagsFilter(tagsFilter)
                    }
                    currentSubscription.subscribe();
                }

                // Handle ticker selection change
                tickerSelect.addEventListener('change', function() {
                    if (centrifuge.state === 'connected') {
                        subscribeToTicker(tickerSelect.value);
                    }
                });

                // Trigger actual connection establishing with a server.
                centrifuge.connect();

                function handleUnsubscribed(ctx) {
                    drawText('Unsubscribed from channel ' + ctx.channel);
                }

                function handleSubscribing(ctx) {
                    drawText('Subscribing to channel ' + ctx.channel);
                }

                function handleSubscribed(ctx) {
                    drawText('Subscribed on channel ' + ctx.channel);
                    statusDiv.className = 'status-connected';
                    statusDiv.textContent = '✓ Subscribed to ticker: ' + tickerSelect.value + ' (tags filtering active)';
                    if (ctx.wasRecovering) {
                        if (ctx.recovered) {
                            drawText('Subscription to ' + ctx.channel + ' recovered');
                        } else {
                            drawText('Subscription to ' + ctx.channel + ' was unable to recover');
                        }
                    }
                }

                function handleSubscriptionError(ctx) {
                    drawText('Subscription error in channel ' + err.channel + ': ' + JSON.stringify(ctx));
                }

                function handlePublication(ctx) {
                    let data = ctx.data;

                    // In protobuf mode, decode binary data
                    if (useProtobuf) {
                        const str = new TextDecoder("utf-8").decode(ctx.data);
                        data = JSON.parse(str);
                    }

                    const ticker = data["ticker"];
                    const bid = data["bid"];
                    const ask = data["ask"];
                    const text  = "Ticker " + ticker + " bid: " + bid + " ask: " + ask;
                    drawText(text);
                }

                function drawText(text) {
                    let e = document.createElement('li');
                    const time = new Date().toLocaleTimeString();
                    e.innerHTML = '<span class="message-time">' + time + '</span><span class="message-content">' + text + '</span>';
                    container.insertBefore(e, container.firstChild);
                }
            });
        </script>
    </head>
    <body>
        <div class="container">
            <div class="card">
                <div class="card-header">
                    <h1>
                        Stock Ticker Feed - Tags Filter
                        {{if .UseProtobuf}}
                        <span class="protocol-badge protocol-protobuf">Protobuf</span>
                        {{else}}
                        <span class="protocol-badge protocol-json">JSON</span>
                        {{end}}
                    </h1>
                    <div style="margin-top: 10px; font-size: 14px;">
                        {{if .UseProtobuf}}
                        <a href="/">← Switch to JSON</a>
                        {{else}}
                        <a href="?protobuf=true">Switch to Protobuf →</a>
                        {{end}}
                    </div>
                </div>
                <div class="card-body">
                    <div id="status" class="status-disconnected">Not connected</div>

                    <div class="controls">
                        <label for="tickerSelect">
                            <svg width="16" height="16" fill="currentColor" class="bi bi-bar-chart-line-fill" viewBox="0 0 16 16" style="vertical-align: text-bottom; margin-right: 4px;">
                                <path d="M11 2a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v12h.5a.5.5 0 0 1 0 1H.5a.5.5 0 0 1 0-1H1v-3a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v3h1V7a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v7h1V2z"/>
                            </svg>
                            Select Stock Ticker:
                        </label>
                        <select id="tickerSelect" class="form-select-sm">
                            <option value="AAPL" selected>🍎 AAPL - Apple Inc.</option>
                            <option value="GOOG">🔍 GOOG - Alphabet Inc.</option>
                            <option value="MSFT">💻 MSFT - Microsoft Corp.</option>
                            <option value="AMZN">📦 AMZN - Amazon.com Inc.</option>
                            <option value="TSLA">⚡ TSLA - Tesla Inc.</option>
                            <option value="META">👥 META - Meta Platforms</option>
                            <option value="NVDA">🎮 NVDA - NVIDIA Corp.</option>
                            <option value="NFLX">🎬 NFLX - Netflix Inc.</option>
                            <option value="ORCL">🗄️ ORCL - Oracle Corp.</option>
                            <option value="CRM">☁️ CRM - Salesforce Inc.</option>
                        </select>
                    </div>

                    <div class="info-text">
                        {{if .UseProtobuf}}
                        <strong>✓ Protobuf Mode:</strong> Using binary protocol with TextEncoder/TextDecoder for efficient data transfer.
                        {{else}}
                        <strong>ℹ️ JSON Mode:</strong> Using JSON protocol for human-readable data transfer.
                        {{end}}
                    </div>

                    <div class="messages-container">
                        <h5 style="color: #334155; margin-bottom: 12px; font-size: 16px; font-weight: 600;">
                            📊 Live Updates
                        </h5>
                        <ul id="messages"></ul>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>
